#include "fccu.h"
#include "fccu_queue.h"
#include <string.h>
#include <stdio.h>

/* user_hook 示例函数 */
static int32_t user_hook_major(uint32_t code, uint64_t detail, bool first)
{
    printf("  [user_hook_major] code=0x%08x, detail=0x%llx, first=%d\n", code, (unsigned long long)detail, first ? 1 : 0);
    return 100;
}
static int32_t user_hook_minor(uint32_t code, uint64_t detail, bool first)
{
    printf("  [user_hook_minor] code=0x%08x, detail=0x%llx, first=%d\n", code, (unsigned long long)detail, first ? 1 : 0);
    return 200;
}

/* 故障注册表，实际项目应由配置或NVM加载 */
static struct FCCU_FaultTableEntry g_fccu_fault_table[FCCU_MAX_FAULT_NUM] = {
    {0x01010001U, 1U, 1U, user_hook_major},   // idx=0
    {0x01010002U, 2U, 1U, user_hook_minor},   // idx=1
    {0x01010003U, 3U, 1U, NULL},              // idx=2
    {0x01010004U, 4U, 1U, NULL},              // idx=3, 后续可注册钩子
    // 其余自动为0
};
/* 多级队列集合 */
static struct FCCU_QueueSet g_fccu_queue_set;

/* 活跃故障状态表（简单位图实现） */
static uint8_t g_active_faults[FCCU_MAX_FAULT_NUM] = {0};

/* 队列溢出回调 */
static void (*g_queue_overflow_callback)(void) = NULL;

/* FCCU模块初始化 */
void Fccu_Init(void)
{
    (void)Fccu_QueueSetInit(&g_fccu_queue_set, sizeof(struct FCCU_VmEntry));
    printf("[FCCU] Initialization complete\n");
    printf("sizeof(struct FCCU_VmEntry) = %zu\n", sizeof(struct FCCU_VmEntry));
}

/* 辅助函数：根据fault_index查找故障表项 */
static struct FCCU_FaultTableEntry* Fccu_FindFaultEntry(uint8_t fault_index)
{
    if (fault_index < FCCU_MAX_FAULT_NUM) {
        return &g_fccu_fault_table[fault_index];
    }
    return NULL;
}

/* 清除故障状态 */
void Fccu_ClearFault(uint32_t fault_index)
{
    if (fault_index < FCCU_MAX_FAULT_NUM) {
        g_active_faults[fault_index] = 0;
        printf("[FCCU] Fault idx=%u cleared\n", fault_index);
    }
}

/* 查询活跃故障数量 */
uint16_t Fccu_GetActiveFaults(void)
{
    uint16_t cnt = 0;
    for (uint32_t i = 0; i < FCCU_MAX_FAULT_NUM; ++i) {
        if (g_active_faults[i]) cnt++;
    }
    printf("[FCCU] Active faults: %u\n", cnt);
    return cnt;
}

/* 设置队列溢出回调 */
void Fccu_SetQueueOverflowCallback(void (*callback)(void))
{
    g_queue_overflow_callback = callback;
}

/* 注册用户自定义故障处理钩子 */
int32_t Fccu_RegisterUserHook(uint32_t fault_index, int32_t (*user_hook)(uint32_t, uint64_t, bool))
{
    if (fault_index < FCCU_MAX_FAULT_NUM) {
        g_fccu_fault_table[fault_index].user_hook = user_hook;
        printf("[FCCU] Register user_hook for idx=%u\n", fault_index);
        return 0;
    }
    return -1;
}

/* 故障上报函数
 * fault_index: 故障索引
 * fault_detail: 故障详细信息
 * priority: 优先级
 */
int32_t Fccu_ReportFaultPoint(uint32_t fault_index, uint64_t fault_detail, uint8_t priority)
{
    struct FCCU_VmEntry entry;
    entry.fault_index = (uint8_t)fault_index;
    entry.fault_detail = fault_detail;
    entry.count = 1U;

    printf("[FCCU] Report fault: idx=%u, detail=0x%llx, priority=%u\n",
           fault_index, (unsigned long long)fault_detail, priority);

    if (Fccu_QueueSetPush(&g_fccu_queue_set, priority, &entry) <= 0)
    {
        /* 队列溢出处理 */
        printf("Queue overflow on level %u!\n", priority);
        if (g_queue_overflow_callback) {
            g_queue_overflow_callback();
        }
        return -1;
    }
    /* 标记故障为活跃 */
    if (fault_index < FCCU_MAX_FAULT_NUM) {
        g_active_faults[fault_index] = 1;
    }
    return 0;
}

/* 故障后处理（按优先级弹出故障处理）
 * ao: AO对象指针
 * ao_priority: AO优先级
 */
void Fccu_ProcessPostEvent(struct QActive *ao, uint8_t ao_priority)
{
    struct FCCU_VmEntry entry;
    uint8_t level;
    int handled = 0;
    while (Fccu_QueueSetPop(&g_fccu_queue_set, &entry, &level) != 0)
    {
        if (level == ao_priority)
        {
            printf("[AO_P%u] Handle fault idx=%u, detail=0x%llx\n",
                   (unsigned int)ao_priority, (unsigned int)entry.fault_index,
                   (unsigned long long)entry.fault_detail);

            /* 查找并调用 user_hook */
            struct FCCU_FaultTableEntry* fe = Fccu_FindFaultEntry(entry.fault_index);
            if (fe && fe->user_hook) {
                int32_t hook_ret = fe->user_hook(fe->fault_code, entry.fault_detail, true);
                printf("  [AO_P%u] user_hook return: %d\n", (unsigned int)ao_priority, hook_ret);
            } else {
                printf("  [AO_P%u] No user_hook for fault idx=%u\n", (unsigned int)ao_priority, (unsigned int)entry.fault_index);
            }
            handled = 1;
        }
    }
    if (!handled) {
        printf("[AO_P%u] No pending faults\n", (unsigned int)ao_priority);
    }
}